/*
 * ir.c
 *
 * Implements an intermediate representation
 *
 * Edited by: Jeremy Hansen, RANDY Compton
 */

#include "ir.h"

int blockID = 2; // Counter for basic block IDs
int tempVar = 0; // Counter for temporary variables

/* ----------------------------------------------------------------------- 
 * Constructs a basic block
 * ----------------------------------------------------------------------- 
 */
struct ir_t *bbl_new(struct ir_t *parent) {
	struct ir_t *bbl = malloc(sizeof(struct ir_t)), *temp;
	// Set the name to the next available name
	bbl->id = malloc(8 * sizeof(char));
	sprintf(bbl->id, "bbl_%d", blockID++);
	// Empty the lists
	bbl->statements = NULL;
	bbl->next = bbl->child = bbl->otherChild = bbl->nextParent = NULL;
	bbl->numbered = 0;
	bbl->stack = NULL;
	if((bbl->parent = parent) != NULL) // Link the parents (if any)
		for(temp = parent; temp != NULL; temp = temp->nextParent) temp->child = bbl;
	add_to_global_ir_list(bbl);
	return bbl;
}

/* ----------------------------------------------------------------------- 
 * Appends a statement to a block
 * ----------------------------------------------------------------------- 
 */
void statement_new(struct tac_t **ss, int type, char *v1, char *v2, char *v3) {
	struct tac_t *stmt = *ss;
	if(stmt == NULL) // Is the list of statements empty?
		stmt = *ss = malloc(sizeof(struct tac_t)); // Put the statement in the list
	else {
		while(stmt->next != NULL) stmt = stmt->next; // Find the end of the list
		stmt = stmt->next = malloc(sizeof(struct tac_t)); // Append the statement
	}
	stmt->type = type;
	stmt->v1 = v1;
	stmt->v2 = v2;
	stmt->v3 = v3;
}

/* ----------------------------------------------------------------------- 
 * Appends a statement with a constant to a block
 * ----------------------------------------------------------------------- 
 */
void const_statement_new(struct tac_t **ss, int type, char *v1, int n2) {
	struct tac_t *stmt = *ss;
	if(stmt == NULL) // Is the list of statements empty?
		stmt = *ss = malloc(sizeof(struct tac_t)); // Put the statement in the list
	else {
		while(stmt->next != NULL) stmt = stmt->next; // Find the end of the list
		stmt = stmt->next = malloc(sizeof(struct tac_t)); // Append the statement
	}
	stmt->type = type;
	stmt->v1 = v1;
	stmt->v2 = NULL;
	stmt->n2 = n2;
}

/* ----------------------------------------------------------------------- 
 * Pushes a statement onto a statement stack
 * ----------------------------------------------------------------------- 
 */
struct tac_t *statement_push(struct tac_t *stack, struct tac_t *s) {
	struct tac_t *temp = malloc(sizeof(struct tac_t));
	memcpy(temp, s, sizeof(struct tac_t)); // Copy the statement
	temp->next = stack; // Link it on the top
	return temp;
}

/* ----------------------------------------------------------------------- 
 * Create a temporary variable name
 * ----------------------------------------------------------------------- 
 */
char *temp_new() {
	char *v = malloc(8 * sizeof(char));
	sprintf(v, "t%d", ++tempVar);
	return v;
}
